#pragma once
#include "util.hpp"
#include "log_msg_set.hpp"
#include "formatter.hpp"
#include <memory>
#include <mutex>
class Logsink
{

public:
   using lptr=std::shared_ptr<Logsink>;//从类内公有定义ptr，因为要Logsink::才能访问故可以简单点
    virtual void log(const char *data, size_t len) = 0;
    virtual ~Logsink() {}
};

class Stdoutsink : public Logsink
{

public:
    void log(const char *data, size_t len) override
    {
        std::cout.write(data, len);
        if (!std::cout.good())
        {
            std::cout << "日志标准输出模式失败\n";
        }
    }
};

class Filesink : public Logsink
{

public:
    Filesink(std::string name) : _filename(name)
    {
        // 不存在进行目录创建：
        if (!File::Isexit(_filename))
        {
            File::Createdir(File::Getpath(_filename));
        }
        _ofs.open(_filename, std::ios::app | std::ios::binary);
        if (!_ofs.good())
        {
            std::cout << "日志指定文件打开失败\n";
            assert(_ofs.is_open());
        }
    }

    std::string &Getfilename()
    {
        return _filename;
    }
    void log(const char *data, size_t len) override
    {      //std::cout<<"开始写入 "<<data<<std::endl;
         _ofs.write(data, len);
         //std::flush(_ofs);         //endl相当于flush+\n 这里直接是写到了缓冲区还没刷新到硬件（除非手动刷新，否则默认只有程序正常完成后才会刷新到硬件）
       // std::cout<<"写入完成"<<std::endl;
        if (!_ofs.good())
        {
            std::cout << "日志指定文件模式输出失败\n";
        }
    }

private:
    std::string _filename;
    std::ofstream _ofs;
};

// 滚动形式：basename20001212231159.log
class Rollfilesink : public Logsink
{

public:
    Rollfilesink(std::string basename, size_t maxsize) : _basename(basename), _maxsize(maxsize)
    {
        // 不存在进行目录创建：
        if (!File::Isexit(_basename))
        {
            File::Createdir(File::Getpath(_basename));
        }
    }
    void log(const char *data, size_t len) override
    {
        // 写之前先要判断文件是否符合要求（_ofs）---> 文件打开正常，没有超过_maxsize
        Initfile();
        _ofs.write(data, len);
        if (_ofs.good() == false)
        {
            std::cout << "日志滚动文件模式输出失败---"<<_cursize<<" " <<_count<<std::endl;
        }
        _cursize += len;
    }

    void Initfile()
    {    
        //good的范围大于is_open，这里应该是is_open
        if (_ofs.is_open() == 0 || _maxsize <= _cursize)
        {
            _ofs.close();//一定不要忘记关闭之前_ofs管理的文件
            _ofs.open(Createfilename(), std::ios::app | std::ios::binary);
            if (!_ofs.good())
            {
                std::cout << "日志滚动文件打开失败\n";

                assert(_ofs.is_open());
            }
            _cursize = 0;
        }
    }

    std::string Createfilename()
    {
        time_t t = time(NULL);
        struct tm lt;
        localtime_r(&t, &lt);
        std::stringstream ss;
        ss << _basename;
        ss << lt.tm_year + 1900;
        ss << lt.tm_mon + 1;
        ss << lt.tm_mday;
        ss << lt.tm_hour;
        ss << lt.tm_min;
        ss << lt.tm_sec;
        ss << "---";
        ss << _count++;
        ss << ".log";
        return ss.str();
    }

private:
    size_t _count = 0;
    std::string _basename;
    std::ofstream _ofs;
    size_t _maxsize;
    size_t _cursize = 0;
};
//改成工厂模式可以支持用户拓展

class Sinkfactory
{

public:
    // 静态模版函数
    template <typename sinkname, typename ... Args>//模版参数args不输入自动根据函数参数默认填入
    static Logsink::lptr Create(Args && ... args)
    {
        return std:: make_shared<sinkname>(std::forward<Args>(args)...);
    }
};












